/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.redkalex.htdi.user;

import java.security.*;
import java.util.function.Predicate;
import java.util.logging.*;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import org.redkale.convert.json.JsonConvert;
import org.redkale.net.http.*;
import org.redkale.service.*;
import org.redkale.source.*;
import org.redkale.util.*;
import org.redkalex.email.*;
import org.redkalex.htdi.base.*;

/**
 *
 * @author zhangjx
 */
@RestService
public class UserService extends AbstractService {

    private static final MessageDigest md5;

    static {
        MessageDigest d = null;
        try {
            d = MessageDigest.getInstance("MD5");
        } catch (Exception ex) {
        }
        md5 = d;
    }

    protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());

    private static final Predicate<String> emailReg = Pattern.compile("^(\\w|\\.|-)+@(\\w|-)+(\\.(\\w|-)+)+$").asPredicate();

    private final int sessionExpireSeconds = 30 * 60;

    private final Object lockSingup = new Object();

    private final Object lockActive = new Object();

    @Resource
    protected JsonConvert convert;

    @Resource
    protected EmailService emailService;

    @Resource(name = "user")
    protected DataSource source;

    @Resource(name = "usersessions")
    protected CacheSource<Integer> sessions;

    @Resource(name = "property.signup.email.title")
    protected String emailTitle;

    @Resource(name = "property.signup.email.html")
    protected String emailHtml;

    @RestMapping(name = "myinfo", comment = "根据登录态获取当前用户信息")
    public UserInfo current(@RestSessionid String sessionid) {
        if (sessionid == null || sessionid.isEmpty()) return null;
        Integer userid = sessions.getAndRefresh(sessionid, sessionExpireSeconds);
        return userid == null ? null : source.find(UserInfo.class, userid);
    }

    @RestMapping(comment = "注销")
    public RetResult logout(@RestSessionid String sessionid) {
        sessions.remove(sessionid);
        return RetResult.success();
    }

    @RestMapping(comment = "用户查询")
    public Sheet<UserInfo> query(QueryBean bean, Flipper flipper) {
        return source.querySheet(UserInfo.class, flipper, bean);
    }

    @RestMapping(auth = false, comment = "用户登录")
    public RetResult<UserInfo> login(LoginBean bean) {
        if (bean == null || bean.getEmail().isEmpty() || bean.getPassword().isEmpty()) return RetCodes.retResult(RetCodes.RET_PARAMS_ILLEGAL); //没参数
        UserInfo user = source.find(UserInfo.class, FilterNode.create("email", FilterExpress.IGNORECASEEQUAL, bean.getEmail()));
        if (user == null) return RetCodes.retResult(RetCodes.RET_USER_NOTEXISTS); //用户不存在 
        if (logger.isLoggable(Level.FINER)) logger.finer("用户信息: " + user + ", " + source.find(UserInfo.class, user.getUserid()));
        if (user.getStatus() != UserInfo.STATUS_NORMAL) return RetCodes.retResult(RetCodes.RET_USER_STATUS_ILLEGAL); //用户状态不正确 
        if (!user.getPassword().equals(Utility.binToHexString(md5.digest(bean.getPassword().getBytes())))) return RetCodes.retResult(RetCodes.RET_USER_PASSWORD_ILLEGAL); //密码不正确 
        sessions.set(sessionExpireSeconds, bean.getSessionid(), user.getUserid());
        return RetResult.success();
    }

    @RestMapping(auth = false, comment = "用户激活")
    public RetResult active(String token, String password) {
        if (token == null || token.isEmpty() || password == null || password.isEmpty()) return RetCodes.retResult(RetCodes.RET_PARAMS_ILLEGAL); //没参数
        synchronized (lockActive) {
            UserDetail user = source.find(UserDetail.class, FilterNode.create("token", FilterExpress.IGNORECASEEQUAL, token));
            if (user == null) return RetCodes.retResult(RetCodes.RET_USER_NOTEXISTS); //用户不存在 
            if (user.getStatus() != UserInfo.STATUS_PENDING) return RetCodes.retResult(RetCodes.RET_USER_STATUS_ILLEGAL); //用户状态不正确
            user.setStatus(UserInfo.STATUS_NORMAL);
            user.setPassword(Utility.binToHexString(md5.digest(password.getBytes())));  //MD5密码
            //更新数据库
            source.updateColumn(user, "status", "password");
            //更新缓存
            source.updateColumn(UserInfo.class, user.getUserid(), ColumnValue.mov("status", user.getStatus()), ColumnValue.mov("password", user.getPassword()));
            if (logger.isLoggable(Level.FINER)) logger.finer("用户信息: " + user);
            return RetResult.success();
        }
    }

    @RestMapping(auth = false, comment = "用户注册")
    public RetResult<UserInfo> signup(UserDetail bean) {
        if (bean == null) return RetCodes.retResult(RetCodes.RET_PARAMS_ILLEGAL); //没参数
        if (bean.getEmail() == null || !emailReg.test(bean.getEmail())) return RetCodes.retResult(RetCodes.RET_USER_EMAIL_ILLEGAL); //邮箱地址不合法
        if (bean.getFirstName().isEmpty() || bean.getLastName().isEmpty()) return RetCodes.retResult(RetCodes.RET_USER_SIGNUP_ILLEGAL); //注册参数无效
        synchronized (lockSingup) {
            if (source.exists(UserDetail.class, FilterNode.create("email", FilterExpress.IGNORECASEEQUAL, bean.getEmail()))) return RetCodes.retResult(RetCodes.RET_USER_EMAIL_EXISTS); //邮箱已存在
            int maxid = source.getNumberResult(UserDetail.class, FilterFunc.MAX, 10000, "userid").intValue();
            bean.setUserid(maxid + 1);
            bean.setCreatetime(System.currentTimeMillis());
            bean.setStatus(UserInfo.STATUS_PENDING); //待激活
            bean.setToken(Utility.uuid()); //激活码
            bean.setPassword("");
            source.insert(bean);
            source.insert(bean.createUserInfo());
            EmailMessage emailmsg = new EmailMessage();
            emailmsg.setTo(bean.getEmail());
            emailmsg.setTitle(emailTitle);
            if (logger.isLoggable(Level.FINER)) logger.finer("注册信息: " + bean);
            emailmsg.setContent(emailHtml.replace("{token}", bean.getToken()));
            super.runAsync(() -> emailService.sendMessage(emailmsg));
            return new RetResult(bean);
        }
    }

    @RestMapping(comment = "更新")
    public RetResult update(UserDetail bean) {
        if (bean == null || bean.getFirstName().isEmpty() || bean.getLastName().isEmpty()) return RetCodes.retResult(RetCodes.RET_PARAMS_ILLEGAL); //注册参数无效
        UserDetail user = source.find(UserDetail.class, bean.getUserid());
        if (user == null) return RetCodes.retResult(RetCodes.RET_USER_NOTEXISTS); //用户不存在 
        user.setFirstName(bean.getFirstName());
        user.setLastName(bean.getLastName());
        if (!bean.getPassword().isEmpty()) user.setPassword(Utility.binToHexString(md5.digest(bean.getPassword().getBytes())));  //MD5密码
        //更新数据库
        source.updateColumn(user, "firstName", "lastName", "password");
        //更新缓存
        source.updateColumn(UserInfo.class, user.getUserid(), ColumnValue.mov("firstName", user.getFirstName()), ColumnValue.mov("lastName", user.getLastName()), ColumnValue.mov("password", user.getPassword()));
        return RetResult.success();
    }
}
